             package com.java.diagnostics.visualizer.gc.solarissupport.postprocessor;
             
             import com.java.diagnostics.visualizer.data.AggregateData;
             import com.java.diagnostics.visualizer.data.DataPoint;
             import com.java.diagnostics.visualizer.data.DataSet;
             import com.java.diagnostics.visualizer.data.TupleData;
             import com.java.diagnostics.visualizer.data.TupleDataBuilder;
             import com.java.diagnostics.visualizer.data.Variant;
             import com.java.diagnostics.visualizer.factory.DataFactory;
             import com.java.diagnostics.visualizer.gc.solarissupport.util.Messages;
             import com.java.diagnostics.visualizer.impl.factory.LogFactory;
             import com.java.diagnostics.visualizer.parser.vgc.InstanceVGCParser;
             import com.java.diagnostics.visualizer.postprocessing.PostProcessor;
             import com.java.diagnostics.visualizer.properties.OutputProperties;
             import java.util.logging.Logger;
             
             public class DerivedOraclePostProcessor
               implements PostProcessor
             {
               private static final DataFactory heapFactory = InstanceVGCParser.heapFactory;
               
               private static final String CALCULATED_DATA = Messages.getString("DerivedOraclePostProcessor.calculated.data.comment");
               
               private static final Logger TRACE = LogFactory.getTrace(DerivedOraclePostProcessor.class);
               
               public void postprocess(DataSet dataSet, OutputProperties properties) {
                 addDerivedData(dataSet);
                 
                 Variant[] variants = dataSet.getVariants();
                 
                 for (int i = 0; i < variants.length; i++) {
                   addDerivedData(variants[i]);
                 }
                 calculateFreeHeapAfter(dataSet);
               }
               
               private void addDerivedData(AggregateData data) {
                 calculateFreeHeapAfter(data);
                 addCumulativeTuples(data);
               }
               
               private void addCumulativeTuples(AggregateData data) {
                 calculateCumulativeData(data, "OracleVGCLabels.used.eden.before", "OracleVGCLabels.used.survivor.before", 
                   "OracleVGCLabels.used.eden.survivor.before");
                 calculateCumulativeData(data, "OracleVGCLabels.used.eden.after", "OracleVGCLabels.used.survivor.after", 
                   "OracleVGCLabels.used.eden.survivor.after");
               }
               
               private void calculateCumulativeData(AggregateData data, String tupleOneLabel, String tupleTwoLabel, String totalTupleLabel)
               {
                 TupleData tupleOne = data.getTupleData(tupleOneLabel);
                 TupleData tupleTwo = data.getTupleData(tupleTwoLabel);
                 
                 if ((data.getTupleData(totalTupleLabel) == null) && 
                   (tupleTwo != null) && (!tupleTwo.isEmpty()) && 
                   (tupleOne != null) && (!tupleOne.isEmpty())) {
                   TupleDataBuilder totalTuple = heapFactory.createTupleData(
                     totalTupleLabel, 
                     Messages.getString(totalTupleLabel), 
                     tupleOne.getXAxis(), tupleOne.getYAxis());
                   totalTuple.setTupleMetaData(tupleOne.getTupleMetaData());
                   DataPoint[] tupleOnePoints = tupleOne.getDataPoints();
                   DataPoint[] tupleTwoPoints = tupleTwo.getDataPoints();
                   if (tupleOnePoints.length != tupleTwoPoints.length) {
                     return;
                   }
                   for (int i = 0; i < tupleOnePoints.length; i++) {
                     double total = tupleTwoPoints[i].getRawY() + 
                       tupleOnePoints[i].getRawY();
                     totalTuple.addDataPoint(tupleOnePoints[i].getSequenceUID(), 
                       tupleOnePoints[i].getRawX(), total, CALCULATED_DATA);
                   }
                   data.add(totalTuple);
                 }
               }
               
               private void calculateFreeHeapAfter(AggregateData data) {
                 try {
                   calculateMissingDifferenceTuple(data, 
                     "OracleVGCLabels.used.heap.after", 
                     "OracleVGCLabels.heap.size.after", 
                     "OracleVGCLabels.free.heap.after");
                 } catch (Throwable t) {
                   TRACE.warning(t.toString());
                 }
               }
               
               private void calculateMissingDifferenceTuple(AggregateData data, String knownTupleLabel, String totalTupleLabel, String differenceTupleLabel)
               {
                 TupleData knownTuple = data.getTupleData(knownTupleLabel);
                 TupleData totalTuple = data.getTupleData(totalTupleLabel);
                 
                 if ((data.getTupleData(differenceTupleLabel) == null) && 
                   (totalTuple != null) && (!totalTuple.isEmpty()) && 
                   (knownTuple != null) && (!knownTuple.isEmpty())) {
                   TupleDataBuilder differenceTuple = heapFactory.createTupleData(
                     differenceTupleLabel, 
                     Messages.getString(differenceTupleLabel), 
                     knownTuple.getXAxis(), knownTuple.getYAxis());
                   differenceTuple.setTupleMetaData(knownTuple.getTupleMetaData());
                   DataPoint[] knownPoints = knownTuple.getDataPoints();
                   DataPoint[] totalPoints = totalTuple.getDataPoints();
                   if (knownPoints.length != totalPoints.length) {
                     return;
                   }
                   for (int i = 0; i < knownPoints.length; i++) {
                     double difference = totalPoints[i].getRawY() - 
                       knownPoints[i].getRawY();
                     differenceTuple.addDataPoint(knownPoints[i].getSequenceUID(), 
                       knownPoints[i].getRawX(), difference, CALCULATED_DATA);
                   }
                   data.add(differenceTuple);
                 }
               }
             }


